#include "stdafx.h"
#include "BaseClass.h"

namespace System {

///////////////////////////////
// Type
Type::Type(const TCHAR* typeName)
{
	size_t size = System::MemString::StrLen(typeName) + 1;
	this->m_TypeName = new TCHAR[size];
	memcpy(this->m_TypeName, typeName, (size - 1) * sizeof(TCHAR));
	this->m_TypeName[size - 1] = 0;
}

Type::~Type()
{
	if(this->m_TypeName != NULL)
	{
		delete this->m_TypeName;
		this->m_TypeName = NULL;
	}
}

const Type* System::Type::GetType()
{
	return TYPE_OF(System_Type);
}

const TCHAR* Type::ToString() const
{
	return this->m_TypeName;
}

const TCHAR* Type::GetFullName() const
{
	return this->m_TypeName;
}

///////////////////////////////
// BaseClass
VIRTUAL_GET_TYPE_IMPLEMENT(System::XObject, System_XObject)
VIRTUAL_TOSTRING_IMPLEMENT(System::XObject, System_XObject)

XObject::XObject() { }

XObject::~XObject(){  }

///////////////////////////////
// MemString
VIRTUAL_GET_TYPE_IMPLEMENT(System::MemString, System_MemString)

MemString::MemString(void)
{
	this->Default();
}

MemString::MemString(const size_t size)
{
	this->Init(size);
}

MemString::MemString(const TCHAR* pstr)
{
	size_t size = System::MemString::StrLen(pstr);
	if(size > 0) {
		this->Init(size);
		memcpy(this->m_Buffer, pstr, size * sizeof(TCHAR));
		this->m_Length = size;
	} else {
		this->Default();
	}
}

MemString::MemString(const TCHAR* pstr, const size_t size)
{
	if(size > 0) {
		this->Init(size);
		memcpy(this->m_Buffer, pstr, size * sizeof(TCHAR));
		this->m_Length = size;
	} else {
		this->Default();
	}
}

MemString::MemString(const MemString& str)
{
	if(str.m_Length > 0){
		this->Init(str.m_Length);
		memcpy(this->m_Buffer, str.m_Buffer, str.m_Length * sizeof(TCHAR));
		this->m_Length = str.m_Length;
	} else {
		this->Default();
	}
}

MemString::~MemString(void)
{
	this->Release();
}

void MemString::Default()
{
	this->m_Length = 0;
	this->m_Capacity = 0;
	this->m_Buffer = NULL;
}

void MemString::Release()
{
	if(this->m_Buffer != NULL)
	{
		delete this->m_Buffer;
		this->m_Buffer = NULL;
		this->m_Capacity = 0;
		this->m_Length = 0;
	}
}

void MemString::Init(const size_t size)
{
	this->m_Length = 0;
	this->m_Capacity = size > 0 ? size + 1 : MEMSTR_DEFAULT_SIZE;
	this->m_Buffer = new TCHAR[this->m_Capacity];
	memset(this->m_Buffer, 0, this->m_Capacity * sizeof(TCHAR));
}

void MemString::Increase(const size_t len)
{
	size_t extend = len + 1;
	size_t total = m_Length + extend;
	if(total > m_Capacity)
	{
		TCHAR* buffer = new TCHAR[total];
		if(this->m_Length > 0) {
			memcpy(buffer, this->m_Buffer, m_Length * sizeof(TCHAR));
			memset(buffer + this->m_Length, 0, extend * sizeof(TCHAR));
		} else {
			memset(buffer, 0, total * sizeof(TCHAR));
		}

		this->Release();
		this->m_Buffer = buffer;
		this->m_Capacity = total;
	}
}

void MemString::Reset()
{
	if(this->m_Length > 0)
	{
		memset(this->m_Buffer, 0, this->m_Length * sizeof(TCHAR));
		this->m_Length = 0;
	}
}

const TCHAR* MemString::ToString() const
{
	return this->GetData();
}

const TCHAR* MemString::GetData() const
{
	return this->m_Buffer;
}

const size_t MemString::Size()
{
	return this->m_Length;
}

MemString& MemString::operator +(const TCHAR ch)
{
	if(m_Length >= m_Capacity)
	{ 
		this->Increase(m_Capacity > 0 ? m_Capacity : MEMSTR_DEFAULT_SIZE);
	}
	this->m_Buffer[m_Length++] = ch;
	return *this;
}

MemString& MemString::operator +(const TCHAR* pstr)
{
	size_t len = System::MemString::StrLen(pstr);
	if(m_Length + len >= m_Capacity)
	{
		this->Increase(len > m_Capacity ? len : m_Capacity);
	}
	memcpy(m_Buffer + m_Length, pstr, len * sizeof(TCHAR));
	m_Length += len;

	return *this;
}

MemString& MemString::operator +(const MemString str)
{
	return *this + str.GetData();
}

MemString& MemString::operator +=(const TCHAR ch)
{
	return *this + ch;
}

MemString& MemString::operator +=(const TCHAR* pstr)
{
	return *this + pstr;
}

MemString& MemString::operator +=(const MemString str)
{
	return *this + str;
}

MemString& MemString::operator =(const TCHAR ch)
{
	this->Reset();
	return *this + ch;
}

MemString& MemString::operator =(const TCHAR* pstr)
{
	this->Reset();
	return *this + pstr;
}

///////////////////////////////

}// end namespace